package jp.sourceforge.akjrcp.videotools.vobmerge;


import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

import jp.sourceforge.akjrcp.akj_betas.Akj_betasPlugin;
import jp.sourceforge.akjrcp.ui.FileOverwriteControler;
import jp.sourceforge.akjrcp.ui.FileSizeProgressMonitor;
import jp.sourceforge.akjrcp.util.ProgressMonitorUtils;
import jp.sourceforge.akjrcp.videotools.dvdtoxvid.CheckToRadio;
import jp.sourceforge.akjrcp.videotools.dvdtoxvid.DVDData;
import jp.sourceforge.akjrcp.videotools.dvdtoxvid.DVDTitleSet;
import jp.sourceforge.akjrcp.videotools.dvdtoxvid.DVDTitleSetComposite;

import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.ScrolledComposite;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.layout.RowLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.DirectoryDialog;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.part.ViewPart;
import org.eclipse.ui.plugin.AbstractUIPlugin;


public class VOBCopyMergeView extends ViewPart {
	public static Log log=LogFactory.getLog(VOBCopyMergeView.class);
	
	public static final String ID = VOBCopyMergeView.class.getName();

	/**
	 * This is a callback that will allow us to create the viewer and initialize
	 * it.
	 */
	DVDTitleSetComposite[] titleSetComposits;

	private Composite composite;

	private DVDData dvdData;

	private ScrolledComposite scroll;

	private Text saveFilePath;

	private Button execButton;
	
	
	private boolean actionCancel;
	
	private String execLabel="    copy merge    ";
	private String cancelLabel="cancel";
	//Process process;

	private Button openButton;
	private boolean cancelling;
	private FileSizeProgressMonitor progressMonitor;

	private Button saveButton;
	public void createPartControl(Composite parent) {
		//parent.setLayout(new GridLayout(1,false));
		parent.setLayout(new GridLayout());
		Composite actionPanel=new Composite(parent,SWT.NULL);
		actionPanel.setLayout(new RowLayout());
		openButton = new Button(actionPanel,SWT.NULL);
		ImageDescriptor opendirIcon = AbstractUIPlugin.imageDescriptorFromPlugin(
				Akj_betasPlugin.PLUGIN_ID, "icons/opendir.gif");
	    openButton.setImage(opendirIcon.createImage());
	    openButton.addSelectionListener(new SelectionListener(){

			public void widgetDefaultSelected(SelectionEvent e) {
				
			}

			public void widgetSelected(SelectionEvent e) {
				openDir();
			}
	    	
	    });
	    
	    
		scroll = new ScrolledComposite(parent,SWT.V_SCROLL|SWT.BORDER);
		GridData gdata=new GridData(GridData.FILL_BOTH);
		gdata.grabExcessVerticalSpace=true;
		//gdata.minimumHeight=200;
		scroll.setLayoutData(gdata);
		
		composite = new Composite(scroll,SWT.NULL);
		composite.setLayoutData(new GridData(GridData.FILL_BOTH));
		composite.setLayout(new GridLayout(1,false));
		
		dvdData = new DVDData();
		scroll.setContent(composite);
		scroll.setMinSize(SWT.DEFAULT,100);//default
		
		scroll.setExpandHorizontal(true);
		scroll.setExpandVertical(true);
		
		Composite execPanel=new Composite(parent,SWT.NONE);
		execPanel.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
		//start button;
		execPanel.setLayout(new GridLayout(3,false));
		execButton = new Button(execPanel,SWT.NULL);
		execButton.setText(execLabel);
		execButton.addSelectionListener(new StartExec());
		
		saveFilePath = new Text(execPanel,SWT.READ_ONLY);
		saveFilePath.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
		
		saveButton = new Button(execPanel,SWT.NULL);
		saveButton.setText("set save file");
		saveButton.addSelectionListener(new SaveFile());
		//audio,bitrate
		//file save
		
		//openDir("e:\\video_ts");
		//saveFilePath.setText("c:\\tmp\\tmp.vob");
		updateExecButton();
	}
	
	
	public void dispose(){
		cancel();//stop copying.
		try {
			Thread.sleep(100); //wait something
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		super.dispose();
	}
	public void cancel(){
		//if(process!=null){
			//process.destroy();//cancel
		//}
		cancelling=true;
		progressMonitor.setCancel(true);
	}
	public class StartExec implements SelectionListener{

		public void widgetDefaultSelected(SelectionEvent e) {
			
		}

		public void widgetSelected(SelectionEvent e) {
			
			if(actionCancel){
				
				cancel();
				
			}else{
			if(saveFilePath.getText().length()==0){
				return;
			}
			
			if(titleSetComposits==null ||titleSetComposits.length==0){
				return;
			}
			
			DVDTitleSetComposite titleSet=null;
			//get selection title
			for(int i=0;i<titleSetComposits.length;i++){
				if(titleSetComposits[i].getSlected()){
					titleSet=titleSetComposits[i];
					break;
				}
			}
			if(titleSet!=null){
				File files[]=titleSet.getEncodingFile();
				
//				mix start.
				exec(files,new File(saveFilePath.getText()));
			}
			
			}
			
			
			
			
		}
		
	}
	
	public class FinishExecute extends Thread{
		public void run(){
			execButton.setText(execLabel);
			actionCancel=false;
			saveButton.setEnabled(true);
			openButton.setEnabled(true);
		}
	}
	public void updateExecButton(){
		if(saveFilePath.getText().length()==0){
			execButton.setEnabled(false);
			return;
		}
		
		if(titleSetComposits==null ||titleSetComposits.length==0){
			execButton.setEnabled(false);
			return;
		}
		
		log.info(titleSetComposits.length);
		
		execButton.setEnabled(true);
	}
	
	public String mixCommand(File files[]){
		String ret="";
		for (int i = 0; i < files.length; i++) {
			ret+="\""+files[i].getAbsolutePath()+"\"";
			if(i!=files.length-1){
				ret+="+";
			}
		}
		/* not work.
		if(files.length==0){
			ret+="+\"\"";//dummy
		}*/
		return ret;
	}
	
	/*
	public class CommandExec extends Thread{
		private String command[];
		public CommandExec(String command[]){
			this.command=command;
		}
		public void run(){

			Runtime r=Runtime.getRuntime();
			try {
				log.info(ArrayUtils.toString(command));
				PrintStreamProcessPrinter s=new PrintStreamProcessPrinter(new PrintWriter(System.out));
				process=r.exec(command);
				ProcessMonitor monitor=new ProcessMonitor(process,s);
				monitor.startMonitor();
				try {
					process.waitFor();
					
					PlatformUI.getWorkbench().getDisplay().syncExec(new FinishExecute());
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}*/
	

	
public class MergeFiles extends Thread{
	private File[] files;
	private File export;
	public MergeFiles(File files[],File export){
		this.files=files;
		this.export=export;
	}
	
	public void run(){
		while(cancelling==false){
			try {
				BufferedOutputStream bout=new BufferedOutputStream(new FileOutputStream(export),10240);
				for (int i = 0; i < files.length; i++) {
					if(cancelling){
						break;
					}
					log.info("open:"+files[i]);
					BufferedInputStream binput=new BufferedInputStream(new FileInputStream(files[i]),10240);
					byte[] bytes=new byte[1024];
					int r;
					while((r=binput.read(bytes))!=-1){
						if(cancelling){
							break;
						}
						//log.inforead:"+r);
						bout.write(bytes,0,r);
					}
					binput.close();
					log.info("close:"+files[i]);
				}
				
				bout.close();
				break;
			} catch (FileNotFoundException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
		}
		
		if(cancelling){
			export.delete();//remove file.
		}
		
		PlatformUI.getWorkbench().getDisplay().syncExec(new FinishExecute());//go back.
	}
}

public void exec(File files[],File export){
	saveButton.setEnabled(false);
	openButton.setEnabled(false);
	
		cancelling=false;
		actionCancel=true;
		execButton.setText(cancelLabel);
		
		
		log.info(ArrayUtils.toString(files));
		log.info(export);
		if(export.exists()){
			boolean r=export.delete();
			if(r==false){
				log.warn("delete-faild:"+export);
				return;
			}
		}
		Thread t=new Thread(new MergeFiles(files,export));
		t.start();
		
		
		progressMonitor=new FileSizeProgressMonitor();
		long total=0;
		for (int i = 0; i < files.length; i++) {
			total+=files[i].length();
		}
		progressMonitor.setFile(export);
		progressMonitor.setProgressMonitor(ProgressMonitorUtils.getProgressMonitor());
		progressMonitor.setMaxFileSize(total);
		progressMonitor.start();
		
	}

	/*
	public void exec(File files[],File export){
		
		actionCancel=true;
		execButton.setText(cancelLabel);
		
		
		log.info(ArrayUtils.toString(files));
		log.info(export);
		File tmpFile=null;
		try {
			String msCommand="copy /b"+" "+mixCommand(files)+" "+"\""+export+"\"";
			tmpFile=File.createTempFile("tmp", ".bat");
			tmpFile.deleteOnExit();
			FileUtils.writeStringToFile(tmpFile, msCommand);
		} catch (IOException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
		if(export.exists()){
			boolean deleted=export.delete();
			if(!deleted){
				log.warn("faild-delete:"+export);
				new FinishExecute();
				return;
			}
		}
		String command[]=new String[6];
		command[0]="cmd.exe";
		command[1]="/c";
		command[2]="copy";
		command[3]="/b";
		command[4]=mixCommand(files);
		command[5]=export.getAbsolutePath();
		
		//command[2]=tmpFile.getAbsolutePath();
		
		Thread t=new Thread(new CommandExec(command));
		t.start();
		
		progressMonitor=new FileSizeProgressMonitor();
		long total=0;
		for (int i = 0; i < files.length; i++) {
			total+=files[i].length();
		}
		progressMonitor.setFile(export);
		progressMonitor.setProgressMonitor(ProgressMonitorUtils.getProgressMonitor());
		progressMonitor.setMaxFileSize(total);
		progressMonitor.start();
		
	}*/
	
	
	public class SaveFile implements SelectionListener{

		public void widgetDefaultSelected(SelectionEvent e) {
			
		}

		public void widgetSelected(SelectionEvent e) {
			
			FileDialog dialog=new FileDialog(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(),SWT.SAVE);
			dialog.setFilterExtensions(new String[]{"*.avi"});
			dialog.setFilterExtensions(new String[]{"*.vob"});
			String path=dialog.open();
			if(path!=null){
				File f=new File(path);
				if(f.exists()){
					FileOverwriteControler controler=new FileOverwriteControler(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(),FileOverwriteControler.MODE_YES_NO_CANCEL);
					boolean r=controler.canOverwrite(f);
					if(r==false){
						return;
					}
				}
				saveFilePath.setText(path);
			}
			
			updateExecButton();
		}
		
	}
	public void openDir(String path){
		if(path==null){
			return;
		}
		
		Control[] cs=composite.getChildren();
		for (int i = 0; i < cs.length; i++) {
			cs[i].dispose();
		}
		
		//dvdData=new DVDData();
		dvdData.open(new File(path));

		CheckToRadio checkToRadio=new CheckToRadio();
		DVDTitleSet[] titleSets=dvdData.getTitleSets();
		log.info("titleset:"+titleSets.length);
		titleSetComposits=new DVDTitleSetComposite[titleSets.length];
		for(int i=0;i<titleSets.length;i++){
			titleSetComposits[i]=new DVDTitleSetComposite(composite,SWT.NONE,titleSets[i],checkToRadio);
			titleSetComposits[i].setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
			//titleSetComposits[i].pack();
		}
		scroll.setMinHeight(140*titleSets.length);
		
		//great way to re-layout.
		scroll.pack();
		scroll.getParent().layout(true);
		
		updateExecButton();
	}
	public void openDir(){
		openButton.setEnabled(false);
		DirectoryDialog dialog=new DirectoryDialog(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell());
		String path=dialog.open();
		openDir(path);
		openButton.setEnabled(true);
	}
	public void setFocus() {
		
	}
	
	
	
		
}